﻿using System;
using System.Collections.Generic;
using System.Text;

using NGE;
using NGE.Net;

namespace MH
{
    public class ClientComponent : Component
    {
        public ClientComponent(string name, Game g)
            : base(name, g)
        {
            session = new Client();
            session.OnConnected += new SessionEvent(session_OnConnected);
            session.OnDisconnected += new SessionEvent(session_OnDisconnected);
            session.OnSent += new SessionEvent(session_OnSent);
            session.OnReceived += new SessionEvent(session_OnReceived);
        }

        void session_OnReceived(object sender, object arg)
        {
            CharacterEventArgs pcea = (CharacterEventArgs)Util.Deserialize(Util.Decompress((byte[])arg));
            if (pcea.Act == CharacterActs.TEST)
            {
                if (pcea.Arg is double)
                {
                    double point1 = (double)pcea.Arg;
                    game.LoopbackDuration = game.RunningTotalSeconds - point1;
                }
            }
            else if (pcea.Act == CharacterActs.SETPC)
            {
                //if (pcea.Arg is PlayerCharacter)
                //{
                //    game.PC = (PlayerCharacter)pcea.Arg;
                //    //game.PC.GetAvatar();

                //    //Controllable = false;
                //    game.SCN = null;
                //    game.SceneCOM.EnterScene(game.LoadScene("mh-000.nscn"));
                //    game.SceneCOM.SetPC(game.PC, tmpLoc, tmpDir);
                //    Controllable = true;

                //    game.PC.InSceneName = "mh-000.nscn";

                //    UploadPC(game.PC);
                //    RequestOPCs();
                //}
            }
            else if (pcea.Act == CharacterActs.SETOPC)
            {
                //if (pcea.Arg is PlayerCharacter)
                //{
                //    PlayerCharacter opc = (PlayerCharacter)pcea.Arg;
                //    int i = game.GetOPCIndex(opc.Name);
                //    if (i < 0)
                //    {
                //        game.OPCs.Add(opc);
                //    }
                //    else
                //    {
                //        game.OPCs[i] = opc;
                //    }
                //} 
                //else if (pcea.Arg is string)
                //{
                //    string cmd = (string)pcea.Arg;

                //    string[] wrds = cmd.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries);

                //    if (wrds[0] == "offline")
                //    {
                //        string name = wrds[1];
                //        int i = game.GetOPCIndex(name);
                //        if (i < 0)
                //        {
                //        }
                //        else
                //        {
                //            game.OPCs.RemoveAt(i);
                //        }
                //    }
                //}  
                //else if (pcea.Arg is Datagram.PlayerCharacterSceneInfo)
                //{
                //    Datagram.PlayerCharacterSceneInfo pcsi = (Datagram.PlayerCharacterSceneInfo)pcea.Arg;
                //    int i = game.GetOPCIndex(pcsi.Name);
                //    if (i > -1)
                //    {
                //        game.OPCs[i].SceneInfo = pcsi;
                //    }
                //    else
                //    {
                //        RequestOPC(pcsi.Name);
                //    }
                //}
                //else if (pcea.Arg is Datagram.PlayerCharacterMoveInfo)
                //{
                //    Datagram.PlayerCharacterMoveInfo pcmi = (Datagram.PlayerCharacterMoveInfo)pcea.Arg;
                //    int i = game.GetOPCIndex(pcmi.Name);
                //    if (i > -1)
                //    {
                //        game.OPCs[i].Move(pcmi);
                //    }
                //    else
                //    {
                //        RequestOPC(pcmi.Name);
                //    }
                //}
                //else if (pcea.Arg is Datagram.PlayerCharacterBattleInfo)
                //{
                //    Datagram.PlayerCharacterBattleInfo pcbi = (Datagram.PlayerCharacterBattleInfo)pcea.Arg;
                //    int i = game.GetOPCIndex(pcbi.Name);
                //    if (i > -1)
                //    {
                //        game.OPCs[i].BattleInfo = pcbi;
                //    }
                //    else
                //    {
                //        RequestOPC(pcbi.Name);
                //    }
                //}
                //else if (pcea.Arg is Datagram.PlayerCharacterSayInfo)
                //{
                //    Datagram.PlayerCharacterSayInfo pcsay = (Datagram.PlayerCharacterSayInfo)pcea.Arg;
                //    int i = game.GetOPCIndex(pcsay.Name);
                //    if (i > -1)
                //    {
                //        game.OPCs[i].SayInfo = pcsay;
                //        game.OPCs[i].SaidStartTime = game.RunningTotalSeconds;
                //    }
                //    else
                //    {
                //        RequestOPC(pcsay.Name);
                //    }
                //}
            }
        }

        void session_OnSent(object sender, object arg)
        {
            //throw new NotImplementedException();
        }

        void session_OnDisconnected(object sender, object arg)
        {
            game.Exit();
        }

        void session_OnConnected(object sender, object arg)
        {
            //if (game.IsOnline)
            //{
            //    RequestPC(0);
            //}
        }

        Client session;
        Microsoft.DirectX.Vector3 tmpLoc = new Microsoft.DirectX.Vector3(13, 13, 0);
        //Direction tmpDir = Direction.U;
        double updateRealSpeedTime;

        public bool IsOnline
        {
            get
            {
                return session.IsConnected;
            }
            set
            {
                if (value == true)
                {
                    if (!session.IsConnected)
                    {
                        session.Connect(game.Option.ServerName, game.Option.ServerPort);
                    }
                }
                else
                {
                    if (session.IsConnected)
                    {
                        session.Disconnect();
                    }
                }
            }
        }
        

        public void RequestTEST()
        {
            CharacterEventArgs pcea = new CharacterEventArgs(CharacterActs.TEST, game.RunningTotalSeconds);
            byte[] data = Util.Compress(Util.Serialize(pcea));
            session.Send(data);
        }

        public void RequestPC(int index)
        {
            CharacterEventArgs pcea = new CharacterEventArgs(CharacterActs.GETPC, index);
            byte[] data = Util.Compress(Util.Serialize(pcea));
            session.Send(data);
        }
        public void RequestOPC(string name)
        {
            CharacterEventArgs pcea = new CharacterEventArgs(CharacterActs.GETOPC, name);
            byte[] data = Util.Compress(Util.Serialize(pcea));
            session.Send(data);
        }
        public void RequestOPCs()
        {
            CharacterEventArgs pcea = new CharacterEventArgs(CharacterActs.GETOPC, null);
            byte[] data = Util.Compress(Util.Serialize(pcea));
            session.Send(data);
        }


        public void UploadExitScene(string pcname)
        {
            CharacterEventArgs pcea = new CharacterEventArgs(CharacterActs.SETPC, pcname);
            byte[] data = Util.Compress(Util.Serialize(pcea));
            session.Send(data);
        }
        public void UploadPC(Character pc)
        {
            pc.UnmontEventHandler();
            Character ppc = (Character)Util.Clone(pc);
            //pc.MountEventHandler(game.SceneCOM.OnPlayerCharacterActCode);
            CharacterEventArgs pcea = new CharacterEventArgs(CharacterActs.SETPC, ppc);
            byte[] data = Util.Compress(Util.Serialize(pcea));
            session.Send(data);
        }
        public void UploadPCSceneInfo(Datagram.PlayerCharacterSceneInfo pcsi)
        {
            CharacterEventArgs pcea = new CharacterEventArgs(CharacterActs.SETPC, pcsi);
            byte[] data = Util.Compress(Util.Serialize(pcea));
            session.Send(data);
        }
        public void UploadPCMoveInfo(Datagram.PlayerCharacterMoveInfo pcmi)
        {
            CharacterEventArgs pcea = new CharacterEventArgs(CharacterActs.SETPC, pcmi);
            byte[] data = Util.Compress(Util.Serialize(pcea));
            session.Send(data);
        }
        public void UploadPCBattleInfo(Datagram.PlayerCharacterBattleInfo pcbi)
        {
            CharacterEventArgs pcea = new CharacterEventArgs(CharacterActs.SETPC, pcbi);
            byte[] data = Util.Compress(Util.Serialize(pcea));
            session.Send(data);
        }
        public void UploadPCSayInfo(Datagram.PlayerCharacterSayInfo pcsay)
        {
            CharacterEventArgs pcea = new CharacterEventArgs(CharacterActs.SETPC, pcsay);
            byte[] data = Util.Compress(Util.Serialize(pcea));
            session.Send(data);
        }
        public override void Heartbeat()
        {
            if (IsOnline == false)
            {
                return;
            }
            //if (game.PC == null)
            //{
            //    return;
            //}
            //if (game.PC.NeedMove > 0)
            //{
            //    return;
            //}
            if (game.Timer.TotalSeconds - updateRealSpeedTime > 1)
            {
                RequestTEST();
                updateRealSpeedTime = game.Timer.TotalSeconds;
            }
        }
    }
}
